﻿/*  WintergraspTimer
    Copyright (C) 2009 Mad Cow Development

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using SpeechLib;
using WintergraspTimer.Classes;
using WintergraspTimer.Properties;

namespace WintergraspTimer
{
    public partial class MainForm : Form
    {
        private DateTime _finish;

        const string APP_NAME = "WintergraspTimer";
        const int MULTIPLIER = 60000; // Minuten
        const string FILENAME = @"FuBar_WintergraspFu.lua";

        public static string ConfigFile;

        const string MAD_COW_STUDIOS_WEBSITE = @"http://madcowstudios.wordpress.com/";
        const string WINTERGRASP_TIMER_WEBSITE = @"http://madcowstudios.wordpress.com/wintergrasp-timer";

        readonly List<Battle> _battles;
        readonly Options _options;
        Battle _selectedBattle;

        private enum LuaCorrectness { Ok, FileDoesNotExist, WrongFileStructure, EmptyFileName };
        
        public MainForm()
        {
            InitializeComponent();

            ConfigFile = Application.StartupPath + @"\config.xml";

            // Fixe Fenstergröße
            FormBorderStyle = FormBorderStyle.FixedDialog;
            MaximizeBox = false;

            // Load options
            _options = OptionsReadWrite.Load(ConfigFile);
            
            // Lese Schlachten
            _battles = new List<Battle>();
            ReadBattlesFromSavedVariables();
            _battles.Sort();

            // Populate ComboBox
            foreach (Battle b in _battles)
            {
                if( b.Time > DateTime.Now)
                    comboBox1.Items.Add(b);
            }

            // If at least one entry is found, select the first entry in the ComboBox
            if (comboBox1.Items.Count > 0)
                comboBox1.SelectedIndex = 0;
            else
            {
                button1.Enabled = false;
                numericUpDown1.Enabled = false;
                comboBox1.Enabled = false;
            }

        }

        private void Timer1Tick(object sender, EventArgs e)
        {
            // Stop both timers
            timer1.Stop();
            timer2.Stop();

            // Set label2 to finished
            label2.Text = "Finished!";

            // Speak the text
            string speachText = _options.SpeachText;
            if (speachText.Contains("$REALM$"))
                speachText = speachText.Replace("$REALM$", _selectedBattle.Realm);

            if (speachText.Contains("$REMAINING$"))
                speachText = speachText.Replace("$REMAINING$", _options.Remaining.ToString());
            try
            {
                const SpeechVoiceSpeakFlags spFlags = SpeechVoiceSpeakFlags.SVSFlagsAsync;
                SpVoice voice = new SpVoice {Volume = _options.Volume};
                voice.Speak(speachText, spFlags);
            }
            catch (Exception)
            {
                MessageBox.Show("Speak error", APP_NAME, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            // Show BalloonTip
            notifyIcon1.BalloonTipTitle = "Timer for " + _selectedBattle.Realm + " has finished.";
            notifyIcon1.BalloonTipText = speachText;
            notifyIcon1.ShowBalloonTip(10000);

            // Show MessageBox
            MessageBox.Show(speachText, APP_NAME, MessageBoxButtons.OK, MessageBoxIcon.Information);
            
            // Shutdown Application
            Application.Exit();
        }

        /// <summary>
        /// Start the timer.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button1Click(object sender, EventArgs e)
        {
            DateTime battleStart = ((Battle)comboBox1.SelectedItem).Time;
            TimeSpan alarm = new TimeSpan(0, (int)numericUpDown1.Value, 0);
            TimeSpan remaining = new TimeSpan(battleStart.Ticks - DateTime.Now.Ticks - alarm.Ticks);
            if (remaining.Ticks < 0)
            {
                MessageBox.Show("Although science has made major improvements over the last decade,\n time travel is still NOT possible!");
                return;
            }

            timer1.Interval = (int)(remaining.Ticks/10000);
            _selectedBattle = (Battle)comboBox1.SelectedItem;

            notifyIcon1.Icon = ((Battle)comboBox1.SelectedItem).Faction.Equals("Alliance") 
                ? Resources.alliance 
                : Resources.horde;

            timer1.Start();
            timer2.Start();

            _finish = battleStart.Subtract(new TimeSpan(0, (int)numericUpDown1.Value, 0));
            SetRemainingTime(RemainingTime(_finish));  
         
            // Disable the form's controls
            button1.Enabled = false;
            numericUpDown1.Enabled = false;
            comboBox1.Enabled = false;            
        }

        private void NumericUpDown1ValueChanged(object sender, EventArgs e)
        {
            timer1.Interval = (int)numericUpDown1.Value * MULTIPLIER;
        }

        private void Timer2Tick(object sender, EventArgs e)
        {
            string remaining = RemainingTime(_finish);
            SetRemainingTime(remaining);
        }

        private static String RemainingTime(DateTime time)
        {            
            TimeSpan diff = time - DateTime.Now;
            DateTime test = new DateTime(diff.Ticks);

            return test.ToString("HH:mm:ss");       
        }

        private void MainWindowResize(object sender, EventArgs e)
        {
            if (FormWindowState.Minimized != WindowState) return;
            notifyIcon1.Visible = true;
            Hide();
        }

        private void NotifyIcon1DoubleClick(object sender, EventArgs e)
        {
            Show();
            WindowState = FormWindowState.Normal;
        }

        private void WiederherstellenToolStripMenuItemClick(object sender, EventArgs e)
        {
            Show();
            WindowState = FormWindowState.Normal;
        }

        private void SchließenToolStripMenuItemClick(object sender, EventArgs e)
        {
            Close();
        }

        #region Private Helpers

        // Sets the label in the main window and the tooltip in traybar to remaining time
        void SetRemainingTime(string remaining)
        {
            label2.Text = remaining;
            notifyIcon1.Text = remaining + " (" + _selectedBattle.Realm + ")";
        }

        void ReadBattlesFromSavedVariables()
        {
            BrowseForSavedVariables();

            // Create reader and open file
            using (TextReader tr = new StreamReader(_options.LuaDir))
            {
                string buffer;
                while ((buffer = tr.ReadLine()) != null)
                {
                    if (buffer.Contains("realms"))
                    {
                        while ((buffer = tr.ReadLine()) != null)
                        {
                            // Read and parse realm name
                            while (!(buffer.Contains("Alliance") || buffer.Contains("Horde")))
                            {
                                buffer = tr.ReadLine();
                                if (buffer == null) return;
                            }
                            int startIndex = buffer.IndexOf("\"");
                            int endIndex = buffer.IndexOf("-");
                            int length = endIndex - startIndex;
                            string realm = buffer.Substring(startIndex + 1, length - 2);

                            // Parse faction
                            startIndex = endIndex + 2;
                            length = buffer.Contains("Alliance") ? 8 : 5;
                            string faction = buffer.Substring(startIndex, length);

                            // Read and parse time
                            buffer = tr.ReadLine();
                            startIndex = buffer.IndexOf("=");
                            endIndex = buffer.IndexOf(",");
                            length = endIndex - startIndex;
                            buffer = buffer.Substring(startIndex + 2, length - 2);
                            long seconds = long.Parse(buffer);

                            // Create a battle object and add it to the battles list
                            Battle battle = new Battle(realm, faction, seconds);
                            _battles.Add(battle);
                        }
                    }
                }
                // Close the stream
                tr.Close();
            }
        }

        private void BrowseForSavedVariables()
        {
            LuaCorrectness correct;

            while ((correct = IsLuaFileCorrect(_options.LuaDir)) != LuaCorrectness.Ok)
            {
                if (correct == LuaCorrectness.EmptyFileName)
                    MessageBox.Show(
                        "This seems to be the first time you start WintergraspTimer.\nPlease browse to \"<wow install dir>\\WTF\\Account\\<your account>\\\" and select \"" +
                        FILENAME + "\".", "Welcome to WintergraspTimer", MessageBoxButtons.OK,
                        MessageBoxIcon.Information);
                if (correct == LuaCorrectness.FileDoesNotExist)
                    MessageBox.Show("The file \"" + _options.LuaDir + "\" does not exist.", "File not found",
                                    MessageBoxButtons.OK, MessageBoxIcon.Error);

                if (correct == LuaCorrectness.WrongFileStructure)
                    MessageBox.Show(
                        "You provided a wrong file.\nPlease make sure that you select <wow install dir>\\WTF\\Account\\<your account>\\" +
                        FILENAME + ".", "Wrong file", MessageBoxButtons.OK, MessageBoxIcon.Error);

                OpenFileDialog fileDialog = new OpenFileDialog { Multiselect = false };
                DialogResult result = fileDialog.ShowDialog();
                // If a user presses cancel, exit the application
                if (result == DialogResult.Cancel)
                    Environment.Exit(0);

                _options.LuaDir = fileDialog.FileName;
            }

            // Save the options
            OptionsReadWrite.Save(ConfigFile, _options);
        }

        private static LuaCorrectness IsLuaFileCorrect(string filename)
        {
            if (filename == "") return LuaCorrectness.EmptyFileName;
            if (!new FileInfo(filename).Exists) return LuaCorrectness.FileDoesNotExist;

            using(TextReader tr = new StreamReader(filename))
            {
                string buffer;
                while( (buffer = tr.ReadLine()) != null)
                {
                    if (buffer.Contains("WintergraspFuDB")) return LuaCorrectness.Ok;
                }
            }

            return LuaCorrectness.WrongFileStructure;
        }

        #endregion // Private Helpers

        private static void ExitToolStripMenuItemClick(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private static void HelpToolStripMenuItem1Click(object sender, EventArgs e)
        {
            Process.Start(WINTERGRASP_TIMER_WEBSITE);
        }

        private void OptionsToolStripMenuItemClick(object sender, EventArgs e)
        {
            OptionsForm optionsForm = new OptionsForm(_options);
            optionsForm.ShowDialog();
            
            // set the numericUpDown control to the options value
            numericUpDown1.Value = _options.Remaining;
        }

        private static void MadCowStudiosToolStripMenuItemClick(object sender, EventArgs e)
        {
            Process.Start(MAD_COW_STUDIOS_WEBSITE);
        }

        private static void AboutToolStripMenuItemClick(object sender, EventArgs e)
        {
            AboutForm about = new AboutForm();
            about.ShowDialog();
        }
    }
}